package com.ruoyi.common.utils;

import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Base64Util {

    public static String code = "UTF-8";
    public static String keyDes = "32e326b5053bc97b895f2c14c228af82";
    public static String keyAes = "32e326b5053bc97b895f2c14c228af82";

    public static String encrypt(String data, String secretKey) {
        try {
            byte[] encrpyted = tripleDES(Cipher.ENCRYPT_MODE, data.getBytes(code), secretKey.getBytes());
            byte[] encoded = Base64.encodeBase64(encrpyted); // Base64 编码
            return new String(encoded);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String decrypt(String data, String key) {
        try {
            byte[] decoded = Base64.decodeBase64(data); // Base64 解码
            byte[] decrypted = tripleDES(Cipher.DECRYPT_MODE, decoded, key.getBytes());// 3DES 解密
            return new String(decrypted, code);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] tripleDES(int opmode, byte[] data, byte[] secretKey) {
        return cipher("DESede", "DESede/CBC/PKCS5Padding", opmode, data, "01234567".getBytes(), secretKey);
    }

    private static byte[] cipher(String algorithm, String transformation, int opmode, byte[] data, byte[] iv, byte[] secretKey) {
        try {
            Key key = SecretKeyFactory.getInstance(algorithm).generateSecret(new DESedeKeySpec(secretKey));
            IvParameterSpec spec = new IvParameterSpec(iv);
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(opmode, key, spec);
            return cipher.doFinal(data);
        } catch (InvalidKeyException | InvalidKeySpecException | NoSuchAlgorithmException
                 | NoSuchPaddingException
                 | IllegalBlockSizeException | BadPaddingException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    public static JSONObject getParam(String merchantNo, Date date){
        JSONObject map = new JSONObject();
        map.put("merchantNo", merchantNo);
        map.put("timestamp", DateUtils.getDate());
        map.put("reqId", UUID.randomUUID().toString().replaceAll("-", ""));
        return map;
    }

    public static String encryptAes(String data, String secretKey) {
        try {
            byte[] encrpyted = tripleAes(Cipher.ENCRYPT_MODE, data.getBytes(code), secretKey.getBytes());
            byte[] encoded = Base64.encodeBase64(encrpyted); // Base64 编码
            return new String(encoded);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] cipherAes(String algorithm, String transformation, int opmode, byte[] data, byte[] iv, byte[] secretKey) {
        try {
            Cipher cipher = Cipher.getInstance(transformation);
            SecretKeySpec keyspec = new SecretKeySpec(secretKey, algorithm);
            IvParameterSpec ivspec = new IvParameterSpec(iv);  // CBC模式，需要一个向量iv，可增加加密算法的强度

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(data);
            return encrypted;
        } catch (InvalidKeyException | NoSuchAlgorithmException
                 | NoSuchPaddingException
                 | IllegalBlockSizeException | BadPaddingException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] tripleAes(int opmode, byte[] data, byte[] secretKey) {
        return cipherAes("AES", "AES/CBC/PKCS5Padding", opmode, data, "dxjf18129979469s".getBytes(), secretKey);
    }


    public static String decryptAes(String data, String key) throws Exception {
        try
        {
            byte[] decoded = Base64.decodeBase64(data); // Base64 解码

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec("dxjf18129979469s".getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(decoded);
            String originalString = new String(original);
            return originalString.trim();
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static void main(String[] args) {
        try {
            Map<String,String> map = new HashMap<>();
            map.put("city","佛山市");
            map.put("idCard","123");
            map.put("phoneNo","13111111111");
            map.put("loanAmount","1");
            map.put("profession","1");
            map.put("salaryType","1");
            map.put("socialSecurity","1");
            map.put("custName","测试");
            map.put("sex","1");
            map.put("age","10");
            JSONObject param = getParam("TEST0001", new Date());
            String paramStr = JSONObject.toJSONString(map);
            String enctryt_data = "";
            String data = "";
            enctryt_data = encrypt(paramStr, keyDes);



            param.put("data", enctryt_data);

            System.out.println("===============DES模式 begin===============");
            System.out.println("请求报文：" + JSONObject.toJSONString(param));
            data = decrypt(enctryt_data, keyDes);
            System.out.println("data解密结果:" + data);
            System.out.println("===============DES模式 end===============");
            System.out.println();
            System.out.println();
            System.out.println("===============AES/CBC/PKCS5Padding模式 begin===============");
            enctryt_data = encryptAes(data, keyAes);
            param.put("data", enctryt_data);
            System.out.println("请求报文：" + JSONObject.toJSONString(param));
            data = decryptAes(enctryt_data, keyAes);
            System.out.println("data解密结果:" + data);
            System.out.println("===============AES/CBC/PKCS5Padding模式 end===============");



            map = new HashMap<>();
            map.put("city","深圳市");
            map.put("cityCode","123");
            map.put("phoneNo","c5f3ec33f1ef1f1f94fb8e4fdd23dec5");
            data = encryptAes( JSONObject.toJSONString(map), keyDes);
            System.out.println("data解密结果:" + data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
